package com.bluetrum.abmate;

import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SwitchCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.PreferenceManager;

import com.bluetrum.ablogger.LogViewerActivity;
import com.bluetrum.abmate.databinding.FragmentSettingsBinding;
import com.bluetrum.abmate.log.AppLogger;
import com.bluetrum.abmate.utils.Utils;
import com.bluetrum.abmate.viewmodels.SharedViewModel;

import java.util.Locale;

import javax.inject.Inject;

import dagger.hilt.android.AndroidEntryPoint;
import dagger.hilt.android.qualifiers.ApplicationContext;
import pub.devrel.easypermissions.EasyPermissions;
import timber.log.Timber;

@AndroidEntryPoint
public class SettingsFragment extends Fragment {

    private static final String TAG = SettingsFragment.class.getSimpleName();

    private static final String WEB_URL_LEGAL = BuildConfig.WEB_URL_LEGAL;
    private static final String WEB_URL_PRIVACY = BuildConfig.WEB_URL_PRIVACY;

    private FragmentSettingsBinding binding;
    private ViewGroup launcherNotificationLayout;
    private SwitchCompat launcherSwitch;
    private ViewGroup quickConnectLayout;
    private SwitchCompat quickConnectSwitch;

    private SharedViewModel mViewModel;

    @Inject
    @ApplicationContext
    Context mApplicationContext;

    private ActivityResultLauncher<Intent> permissionsLauncher;
    private ActivityResultLauncher<String> locationPermissionLauncher;
    private ActivityResultLauncher<String[]> bluetoothPermissionLauncher;

    private boolean attemptToEnableQuickConnect = false;

    // Log Verbose Mode
    private static final int REQUIRED_CLICK_COUNT = 7; // 设置所需的连续点击次数
    private static final int TIME_WINDOW = 500; // 设置时间窗口

    private int clickCount = 0;
    private long lastClickTime = 0;
    private boolean showedLogView = false;

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        mViewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        binding = FragmentSettingsBinding.inflate(inflater, container, false);

        // Sometimes crash while using ViewBinding in SharedPreferences.OnSharedPreferenceChangeListener
        launcherNotificationLayout = binding.getRoot().findViewById(R.id.launcherNotificationLayout);
        launcherSwitch = binding.getRoot().findViewById(R.id.launcherSwitch);
        launcherSwitch.setOnClickListener(this::tapLauncherSwitch);
        quickConnectLayout = binding.getRoot().findViewById(R.id.quickConnectLayout);
        quickConnectSwitch = binding.getRoot().findViewById(R.id.quickConnectSwitch);
        quickConnectSwitch.setOnClickListener(this::tapQuickConnectSwitch);

//        binding.launcherSwitch.setOnClickListener(this::tapLauncherSwitch);
        binding.legalView.setOnClickListener(this::tapLegalView);
        binding.privacyView.setOnClickListener(this::tapPrivacyView);
        binding.locationSettingsLayout.setOnClickListener(this::requestLocationPermission);
        binding.bluetoothSettingsLayout.setOnClickListener(this::requestBluetoothPermission);

        permissionsLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    updateLocationPermissionStatus();
                    updateBluetoothPermissionStatus();
                }
        );
        locationPermissionLauncher = registerForActivityResult(
                new ActivityResultContracts.RequestPermission(),
                result -> updateLocationPermissionStatus()
        );
        bluetoothPermissionLauncher = registerForActivityResult(
                new ActivityResultContracts.RequestMultiplePermissions(),
                result -> updateBluetoothPermissionStatus()
        );

        return binding.getRoot();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // For logging
        binding.logViewContainer.setVisibility(View.GONE);
        binding.iconImageView.setOnClickListener(this::clickIcon);

        // 显示版本号
        String appVersion = String.format(Locale.getDefault(),
                binding.textViewAppVersion.getText().toString(), BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE);
        binding.textViewAppVersion.setText(appVersion);

        // 检查快速启动通知栏
        // 这里不能使用匿名类，不然会被GC回收
        PreferenceManager.getDefaultSharedPreferences(mApplicationContext)
                .registerOnSharedPreferenceChangeListener(onSharedPreferenceChangeListener);

        // Location permission is no needed while on Android S or above
        // Bluetooth permission is needed while on Android S or above
        if (Utils.isAndroid12OrAbove()) {
            binding.locationAccessContainer.setVisibility(View.GONE);
            binding.bluetoothPermissionContainer.setVisibility(View.VISIBLE);
        } else {
            binding.locationAccessContainer.setVisibility(View.VISIBLE);
            binding.bluetoothPermissionContainer.setVisibility(View.GONE);
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        updateLauncherNotificationStatus();
        updateQuickConnectState();

        if (Utils.isAndroid12OrAbove()) {
            updateBluetoothPermissionStatus();
        } else {
            updateLocationPermissionStatus();
        }
    }

    private void requestAppPermission(View view) {
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + requireActivity().getPackageName()));
        permissionsLauncher.launch(intent);
    }

    private void requestLocationPermission(View view) {
        if (Utils.isLocationPermissionDeniedForever(requireActivity())) {
            requestAppPermission(view);
        } else {
            Utils.markLocationPermissionRequested(requireContext());
            locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION);
        }
    }

    private void requestBluetoothPermission(View view) {
        if (Utils.isAndroid12OrAbove()) {
            if (Utils.isBluetoothPermissionDeniedForever(requireActivity())) {
                requestAppPermission(view);
            } else {
                Utils.markBluetoothPermissionsRequested(requireContext());
                bluetoothPermissionLauncher.launch(new String[] { Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT });
            }
        }
    }

    // 不能使用匿名类，不然会被GC回收
    private final SharedPreferences.OnSharedPreferenceChangeListener
            onSharedPreferenceChangeListener = (sharedPreferences, key) -> {
        Timber.tag(TAG).d("Preference changed: %s", key);
        if (Utils.PREFS_ENABLE_LAUNCHER_NOTIFICATION.equals(key)) {
            updateLauncherNotificationStatus();
        } else if (Utils.PREFS_ENABLE_QUICK_CONNECT.equals(key)) {
            updateQuickConnectState();
        }
    };

    private void tapLauncherSwitch(View view) {
        boolean isChecked = binding.launcherSwitch.isChecked();
        Utils.setPrefsEnableLaunchNotification(mApplicationContext, isChecked);
        // 在任务管理器隐藏
        Utils.setAppExcludeFromRecents(mApplicationContext, isChecked);
    }

    private void tapQuickConnectSwitch(View view) {
        boolean isChecked = binding.quickConnectSwitch.isChecked();
        if (isChecked) {
            if (Utils.isAndroid12OrAbove()) {
                if (Utils.isBluetoothScanAndConnectPermissionsGranted(requireContext())) {
                    Utils.setPrefsEnableQuickConnect(mApplicationContext, true);
                } else {
                    binding.quickConnectSwitch.setChecked(false);
                    new AlertDialog.Builder(requireContext())
                            .setMessage(R.string.app_settings_quick_connect_bluetooth_permission)
                            .setPositiveButton(R.string.ok, (dialog, which) -> {
                                attemptToEnableQuickConnect = true;
                                requestBluetoothPermission(view);
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                }
            } else {
                if (Utils.isLocationPermissionsGranted(requireContext())) {
                    Utils.setPrefsEnableQuickConnect(mApplicationContext, true);
                } else {
                    binding.quickConnectSwitch.setChecked(false);
                    new AlertDialog.Builder(requireContext())
                            .setMessage(R.string.app_settings_quick_connect_location_permission)
                            .setPositiveButton(R.string.ok, (dialog, which) -> {
                                attemptToEnableQuickConnect = true;
                                requestLocationPermission(view);
                            })
                            .setNegativeButton(R.string.cancel, null)
                            .show();
                }
            }
        } else {
            attemptToEnableQuickConnect = false;
            Utils.setPrefsEnableQuickConnect(mApplicationContext, false);
        }
    }

    private void tapLegalView(View view) {
        Intent intent = new Intent(requireContext(), WebViewActivity.class);
        intent.putExtra(WebViewActivity.WEB_URL, WEB_URL_LEGAL);
        startActivity(intent);
    }

    private void tapPrivacyView(View view) {
        Intent intent = new Intent(requireContext(), WebViewActivity.class);
        intent.putExtra(WebViewActivity.WEB_URL, WEB_URL_PRIVACY);
        startActivity(intent);
    }

    private void updateQuickConnectState() {
        boolean enableQuickConnect = Utils.getPrefsEnableQuickConnect(mApplicationContext);
        quickConnectSwitch.setChecked(enableQuickConnect);
        if (enableQuickConnect) {
            quickConnectLayout.setBackgroundResource(R.color.app_settings_enabled_background_color);
        } else {
            quickConnectLayout.setBackgroundResource(R.color.app_settings_disabled_background_color);
        }
    }

    private void updateLauncherNotificationStatus() {
        boolean enableLauncherNotification = Utils.getPrefsEnableLaunchNotification(mApplicationContext);
        launcherSwitch.setChecked(enableLauncherNotification);
        // 设置背景颜色
        if (enableLauncherNotification) {
            launcherNotificationLayout.setBackgroundResource(R.color.app_settings_enabled_background_color);
        } else {
            launcherNotificationLayout.setBackgroundResource(R.color.app_settings_disabled_background_color);
        }
    }

    private void updateLocationPermissionStatus() {
        boolean hasLocationPermission = Utils.isLocationPermissionsGranted(requireActivity());
        if (hasLocationPermission) {
            binding.locationSettingsLayout.setBackgroundResource(R.color.app_settings_enabled_background_color);

            if (attemptToEnableQuickConnect) {
                Utils.setPrefsEnableQuickConnect(requireContext(), true);
                updateQuickConnectState();
            }
        } else {
            binding.locationSettingsLayout.setBackgroundResource(R.color.app_settings_disabled_background_color);
            // No location permission, no Quick Connect
            if (Utils.getPrefsEnableQuickConnect(requireContext())) {
                Toast.makeText(requireContext(), R.string.app_settings_quick_connect_will_be_disabled, Toast.LENGTH_SHORT).show();
            }
            attemptToEnableQuickConnect = false;
            Utils.setPrefsEnableQuickConnect(requireContext(), false);
            updateQuickConnectState();
        }
    }

    private void updateBluetoothPermissionStatus() {
        boolean hasBluetoothPermission = Utils.isBluetoothScanAndConnectPermissionsGranted(requireContext());
        if (hasBluetoothPermission) {
            binding.bluetoothSettingsLayout.setBackgroundResource(R.color.app_settings_enabled_background_color);

            if (attemptToEnableQuickConnect) {
                Utils.setPrefsEnableQuickConnect(requireContext(), true);
                updateQuickConnectState();
            }
        } else {
            binding.bluetoothSettingsLayout.setBackgroundResource(R.color.app_settings_disabled_background_color);
            // No bluetooth permission, no Quick Connect
            if (Utils.getPrefsEnableQuickConnect(requireContext())) {
                Toast.makeText(requireContext(), R.string.app_settings_quick_connect_will_be_disabled, Toast.LENGTH_SHORT).show();
            }
            attemptToEnableQuickConnect = false;
            Utils.setPrefsEnableQuickConnect(requireContext(), false);
            updateQuickConnectState();
        }
    }

    // Log Verbose Mode

    private void clickIcon(View v) {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastClickTime > TIME_WINDOW) {
            // 时间间隔超过时间窗口，重置计数器
            clickCount = 0;
        }

        clickCount++;
        lastClickTime = currentTime;

        if (clickCount == REQUIRED_CLICK_COUNT) {
            if (showedLogView) {
                enableLogVerboseMode();
            } else {
                showLogView();
            }
        }
    }

    private void showLogView() {
        binding.logViewLayout.setOnClickListener(this::openLogView);
        binding.logViewContainer.setVisibility(View.VISIBLE);

        showedLogView = true;
        Toast.makeText(requireContext(), "Showed log option", Toast.LENGTH_SHORT).show();
    }

    private void openLogView(View v) {
        Intent intent = new Intent(requireContext(), LogViewerActivity.class);
        startActivity(intent);
    }

    private void enableLogVerboseMode() {
        AppLogger.enableVerboseMode();
        binding.textViewLogView.setTextColor(Color.RED);
        Toast.makeText(requireContext(), "Log verbose mode enabled", Toast.LENGTH_SHORT).show();
    }
}